package com.syh.jn.scm.domain.operation.entity.system;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.exception.IllegalParameterException;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.util.other.IdWorker;
import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.domain.AbstractSimpleAggregate;
import com.syh.jn.scm.domain.operation.repository.system.OperationMenuRepository;
import com.syh.jn.scm.dto.operation.system.menu.OperaMenuMto;
import com.syh.jn.scm.dto.operation.system.menu.OperaMenuSto;
import com.syh.jn.scm.exception.BusinessException;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class OperationMenu extends AbstractSimpleAggregate<Long> {
  /**
   * 上级菜单
   */
  private Long superId;
  /**
   * 菜单级别名称
   */
  private String name;
  /**
   * 唯一编码
   */
  private String code;
  /**
   * 类型 1、目录 2、菜单 3、按钮
   */
  private Short type;
  /**
   * 类型 -1 停用 1 启用
   */
  private Short status;
  /**
   * -1 显示 1 隐藏
   */
  private Short hidden;
  /**
   * 排序
   */
  private Short orderLevel;
  /**
   * 页面路由
   */
  private String path;
  /**
   * 显示图标
   */
  private String icon;
  /**
   * 所属终端系统:DOWNSTREAM,OPERATION,SUPPLIER,UPSTREAM
   */
  private String terminalType;
  /**
   * 目录树    格式：1-11-12  1：父父类id，11：父类id，12：当前id
   */
  private String catalogCode;
  /**
   * 父菜单
   */
  private OperationMenu parent;
  /**
   * 子菜单
   */
  private List<OperationMenu> subOperationMenus;
  /**
   *
   */
  private static final Long DEFUALT_SUPERID = Long.valueOf(0);

  public static OperationMenu create(OperaMenuSto sto) {
    OperationMenu operationMenu = new OperationMenu();
    operationMenu.initDefault();
    ValidationUtils.validate(sto);
    ExtBeanUtils.copyProperties(sto, operationMenu);
    if (operationMenu.superId == null) {
      operationMenu.superId = DEFUALT_SUPERID;

      if (ExtStringUtils.isBlank(sto.getTerminalType())) {
        throw new IllegalParameterException("终端类型不能为空");
      }
      if ("DOWNSTREAM,OPERATION,SUPPLIER,UPSTREAM".indexOf(sto.getTerminalType()) < 0) {
        throw new IllegalParameterException("终端类型不在规定范围内");
      }
    }
    if (operationMenu.superId > 0) {
      OperationMenuRepository operationMenuRepository = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);
      OperationMenu fatherOperationMenu = operationMenuRepository.getById(operationMenu.superId);
      if (fatherOperationMenu == null) {
        throw new BusinessException("父分类不存在！");
      }
      operationMenu.setTerminalType(fatherOperationMenu.getTerminalType());
    }

    if (operationMenu.getType().intValue() == 2 && ExtStringUtils.isEmpty(operationMenu.getPath())) {
      throw new BusinessException("菜单类型路由路径不能为空!");
    }
    if (operationMenu.getType().intValue() == 3) {
      operationMenu.setPath("");
      operationMenu.setIcon("");
    }

    IdWorker idWorker = new IdWorker(1);
    if (ExtStringUtils.isBlank(sto.getCode())) {
      String code = Long.toString(idWorker.nextId(), 36);
      operationMenu.setCode(code);
    } else {
      if (!operationMenu.codeIsUnique(sto.getCode())) {
        throw new BusinessException("编码已存在");
      }
    }

    operationMenu.status = 1;
    return operationMenu;
  }

  public void modify(OperaMenuMto menuMto) {
    ExtAssert.notNull(menuMto, "对象为空");
    ValidationUtils.validate(menuMto);
    if (!this.codeIsUnique(menuMto.getId(), menuMto.getCode())) {
      throw new BusinessException("编码已存在");
    }

    this.lastUpdateTimeStamp = System.currentTimeMillis();
    ExtBeanUtils.copyProperties(menuMto, this, false);

    if (this.getType().intValue() == 2 && ExtStringUtils.isEmpty(this.getPath())) {
      throw new BusinessException("菜单类型路由路径不能为空!");
    }
    if (this.getType().intValue() == 3) {
      this.setPath("");
      this.setIcon("");
    }

  }

  public void destroy() {
    OperationMenuRepository menuRead = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);

    if (menuRead.getCount(Wrapper.build().append(Restrictions.rightLike("catalogCode", this.catalogCode))) > 1) {
      throw new BusinessException("该分类存在子分类，删除失败！");
    }
  }

  public void enabled() {
    this.status = 1;

    //判断该菜单是否拥有父菜单
    if (this.superId != null && !this.superId.equals(DEFUALT_SUPERID)) {
      OperationMenuRepository operationMenuRepository = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);
      //修改父菜单状态
      this.parent = getAllParent(operationMenuRepository, this.superId);
      this.updateParentStatus(this.parent, this.status);
    }
  }

  public void disabled() {
    this.status = -1;

    OperationMenuRepository operationMenuRepository = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);
    int subNums = operationMenuRepository.getCount(Wrapper.build().append(Restrictions.eq("superId", this.id)));
    //查看当前菜单是否拥有子菜单
    if (subNums > 0) {
      //修改子菜单状态
      this.subOperationMenus = this.getAllSubMenus(operationMenuRepository, this.id);
      updateSubMenuStatus(this.subOperationMenus, this.status);
    }
  }

  /**
   * 获取所有父菜单
   */
  private OperationMenu getAllParent(OperationMenuRepository operationMenuRepository, Long supId) {
    OperationMenu parent = operationMenuRepository.getById(supId);
    if (parent.getSuperId() != null && !parent.getSuperId().equals(Long.valueOf(0)) && !parent.getStatus().equals(Short.valueOf("1"))) {
      parent.setParent(getAllParent(operationMenuRepository, parent.getSuperId()));
    }
    return parent;
  }

  /**
   * 判断生成的编码是否唯一
   *
   * @param code
   * @return
   */
  private boolean codeIsUnique(String code) {
    OperationMenuRepository operationMenuRepository = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);
    return operationMenuRepository.getCount(Wrapper.build().append(Restrictions.eq("code", code))) == 0;
  }

  /**
   * 判断生成的编码是否唯一
   *
   * @param code
   * @return
   */
  private boolean codeIsUnique(Long id, String code) {
    OperationMenuRepository operationMenuRepository = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);
    return operationMenuRepository.getCount(Wrapper.build().append(Restrictions.eq("code", code)).append(Restrictions.ne("id", id))) == 0;
  }

  /**
   * 修改父菜单状态
   */
  private void updateParentStatus(OperationMenu parent, Short status) {
    parent.status = status;
    if (parent.getSuperId() != null && !parent.getSuperId().equals(Long.valueOf(0))) {
      OperationMenuRepository operationMenuRepository = (OperationMenuRepository) SpringContextUtils.getBean(OperationMenuRepository.class);
      OperationMenu project = operationMenuRepository.getById(parent.getSuperId());
      parent.setParent(project);

      updateParentStatus(parent.getParent(), status);
    }
  }

  /**
   * 获取所有子菜单
   */
  private List<OperationMenu> getAllSubMenus(OperationMenuRepository operationMenuRepository, Long id) {
    List<OperationMenu> subOperationMenus = operationMenuRepository.getList(Wrapper.build().append(Restrictions.eq("superId", id)));
    subOperationMenus.forEach(subMenu -> {
      subMenu.setSubOperationMenus(this.getAllSubMenus(operationMenuRepository, subMenu.getId()));
    });
    return subOperationMenus;
  }

  /**
   * 修改子菜单状态
   */
  private void updateSubMenuStatus(List<OperationMenu> subOperationMenus, Short status) {
    subOperationMenus.forEach(subMenu -> {
      if (subMenu.getSubOperationMenus() != null)
        this.updateSubMenuStatus(subMenu.getSubOperationMenus(), status);
      subMenu.status = status;
    });
  }
}
